package com.esunny.dns.ai.task;

import java.util.Date;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 指定一系列任务，他将无限的循环重复执行，直到调用abort
 * 
 * @author jenvin 2012-6-29 下午3:36:32
 */
public class ScheduledTaskQueueImpl implements TaskQueue {

    private static final Log            log                      = LogFactory.getLog(ScheduledTaskQueueImpl.class);
    private ConcurrentLinkedQueue<Task> queue                    = new ConcurrentLinkedQueue<Task>();              // 保存任务引用
    private ScheduledExecutorService    scheduledExecutorService = null;
    private final AtomicInteger         threadNumber             = new AtomicInteger(1);
    private int                         corePoolSize             = 1;
    private String                      poolName                 = "defaultPool";
    private long                        period                   = 1 * 1000 * 60;

    public ScheduledTaskQueueImpl(){
    }

    @Override
    public void start() {

        scheduledExecutorService = Executors.newScheduledThreadPool(corePoolSize, new ThreadFactory() {

            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r, poolName + "-thread-" + threadNumber.getAndIncrement());
                return t;
            }
        });
    }

    /*
     * (non-Javadoc)
     * @see com.esunny.dns.ai.task.Queue#enqueueTask(com.esunny.dns.ai.task.Task)
     */
    @Override
    public void enqueueTask(final Task task) {
        queue.offer(task);
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {

            @Override
            public void run() {
                try {
                    long l = System.currentTimeMillis();
                    task.execute();
                    if (log.isInfoEnabled()) {
                        log.info("task " + task.toString() + " executed at:" + new Date() + "!consuming time:"
                                 + (System.currentTimeMillis() - l) + " ms");
                    }
                } catch (Exception ex) {

                }
            }
        }, 0, period, TimeUnit.MILLISECONDS);
    }

    @Override
    public void stop() {

        abort();
    }

    @Override
    public void abort() {
        scheduledExecutorService.shutdown();
    }

    public int getCorePoolSize() {
        return corePoolSize;
    }

    public void setCorePoolSize(int corePoolSize) {
        this.corePoolSize = corePoolSize;
    }

    public String getPoolName() {
        return poolName;
    }

    public void setPoolName(String poolName) {
        this.poolName = poolName;
    }

    public long getPeriod() {
        return period;
    }

    public void setPeriod(long period) {
        this.period = period;
    }

    public static void main(String[] args) throws InterruptedException {
        Task[] tasks = new Task[4];
        tasks[0] = new SystemOutTask(1, "task1");
        tasks[1] = new SystemOutTask(1, "task2");
        tasks[2] = new SystemOutTask(1, "task3");
        tasks[3] = new SystemOutTask(1, "task4");
        ScheduledTaskQueueImpl queue = new ScheduledTaskQueueImpl();
        queue.setCorePoolSize(4);
        queue.setPeriod(1 * 1000);
        queue.start();
        for (Task t : tasks) {
            queue.enqueueTask(t);
        }
        Thread.sleep(20000);

        queue.abort();
    }

    public static class SystemOutTask implements Task {

        private int    i    = 0;
        private String name = null;

        public SystemOutTask(int i, String name){
            this.i = i;
            this.name = name;
        }

        @Override
        public void execute() {
            System.out.println(name + "-" + i++);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
